﻿#region Imports
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using CommonUtilities.Enums;
using CommonUtilities.Exceptions;
using CommonUtilities.Extensions;
using CommonUtilities.Logging;
using CommonUtilities.Properties;
using Microsoft.VisualBasic.ApplicationServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endregion

namespace CommonUtilities.Test.UTLogging
{
    /// <summary>
    ///This is a test class for Logger_Test and is intended
    ///to contain all Logger_Test Unit Tests
    ///</summary>
    [TestClass()]
    public class Logger_Test
    {
        private TestContext testContextInstance;
        private string sBasePath = Assembly.GetExecutingAssembly().Location.GetDirectoryNameFull();
        private string sEventSource = new AssemblyInfo(Assembly.GetExecutingAssembly()).Title;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestMethod]
        public void AllowToAll_Test()
        {
            bool allowToAll = true;
            bool allowToEventLog = false;
            bool allowToFile = false;
            string logPath = sBasePath + @"\SampleLog.log";

            if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);
            if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

            MessageBox.Show("Select 'YES' in the next dialog boxes, if prompted..");
            Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);

            Assert.AreEqual(true, target.AllowToFile);
            Assert.AreEqual(true, target.AllowToEventLog);
        }

        [TestMethod]
        public void LogProperties_Test()
        {
            bool allowToAll = true;
            bool allowToEventLog = false;
            bool allowToFile = false;
            string logPath = sBasePath + @"\SampleLog.log";

            if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);
            if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

            MessageBox.Show("Select 'YES' in the next dialog boxes, if prompted..");
            Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);

            ObservableCollection<string> actualPropName = new ObservableCollection<string>();
            "AllowToEventLog,AllowToFile".Split(',')._ForEach(s => actualPropName.Add(s));

            foreach (PropertyInfo prop in target.LogProperties)
            {
                Assert.AreEqual(prop.Name, actualPropName._Where(s => s == prop.Name).FirstOrDefault());
            }

            actualPropName.Add("InvalidProperty");
            foreach (string s in actualPropName)
            {
                string propName = target.LogProperties._Where(prop => prop.Name == s)._Select(prop => prop.Name).FirstOrDefault();
                if (propName.IsNull()) Assert.AreNotEqual(s, propName);
                else Assert.AreEqual(s, propName);
            }
        }

        [TestMethod]
        public void IsAnyLogSelected_Test()
        {
            try
            {
                bool allowToAll = true;
                bool allowToEventLog = false;
                bool allowToFile = false;
                string logPath = sBasePath + @"\SampleLog.log";

                if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);
                if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

                MessageBox.Show("Select 'YES' in the next dialog boxes, if prompted..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);

                Assert.AreEqual(target.IsAnyLogSelected, target.AllowToFile & target.AllowToEventLog); // true
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }

            try
            {
                bool allowToAll = false;
                bool allowToEventLog = true;
                bool allowToFile = false;
                string logPath = sBasePath + @"\SampleLog.log";

                if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);
                if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

                MessageBox.Show("Select 'YES' in the next dialog boxes, if prompted..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);

                Assert.AreEqual(target.IsAnyLogSelected, target.AllowToFile | target.AllowToEventLog); // false
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(Resources.Logger_Msg_LogNotEnabled, ex.Message);
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_1()
        {
            #region All log-options selected
            try
            {
                bool allowToAll = true;
                bool allowToEventLog = false;
                bool allowToFile = false;
                string logPath = sBasePath + @"\SampleLog.log";

                if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);
                if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

                MessageBox.Show("Select 'YES' in the next dialog boxes, if prompted..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);

                Assert.IsTrue(EventLog.SourceExists(sEventSource) && logPath.ValidatePath(ePathValidation.File));
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_2()
        {
            #region Regression : No log-option selected
            try
            {
                bool allowToAll = false;
                bool allowToEventLog = false;
                bool allowToFile = false;
                string logPath = string.Empty;

                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(Resources.Logger_Msg_LogNotEnabled, ex.Message);
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_3()
        {
            #region Regression : Invalid invalid log-file provided
            try
            {
                bool allowToAll = false;
                bool allowToEventLog = false;
                bool allowToFile = true;
                string logPath = @"A:\ActivityLog.log";

                MessageBox.Show("Select 'YES' in the next dialog, if prompted..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(Resources.Logger_Msg_CreateLog_Error.FormatTextFromParams(ex.InnerException.Message), ex.Message);
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_4()
        {
            #region Regression : Log-file creation skipped
            try
            {
                bool allowToAll = false;
                bool allowToEventLog = false;
                bool allowToFile = true;
                string logPath = sBasePath + @"\SampleLog.log";

                if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);

                MessageBox.Show("Select 'NO' in the next dialog, if prompted..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(Resources.Logger_Msg_LogNotCreated, ex.Message);
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_5()
        {
            #region Log-file created
            try
            {
                bool allowToAll = false;
                bool allowToEventLog = false;
                bool allowToFile = true;
                string logPath = sBasePath + @"\SampleLog.log";

                if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);

                MessageBox.Show("Select 'YES' in the next dialog, if prompted..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);

                Assert.IsTrue(logPath.ValidatePath(ePathValidation.File));
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_6()
        {
            #region Regression : Event-source creation skipped
            try
            {
                bool allowToAll = false;
                bool allowToEventLog = true;
                bool allowToFile = false;
                string logPath = string.Empty;

                if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

                MessageBox.Show("Select 'NO' in the next dialog..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(Resources.Logger_Msg_AppEventNotRegistered, ex.Message);
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for Logger Constructor
        ///</summary>
        [TestMethod]
        public void LoggerConstructor_Test_7()
        {
            #region Event-source created
            try
            {
                bool allowToAll = false;
                bool allowToEventLog = true;
                bool allowToFile = false;
                string logPath = string.Empty;

                if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

                MessageBox.Show("Select 'YES' in the next dialog..");
                Logger target = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(Resources.Logger_Msg_AppEventNotRegistered, ex.Message);
            }
            catch (Exception ex)
            {
                throw new UnitTestFailedException(ex);
            }
            #endregion
        }

        /// <summary>
        ///A test for WriteToLog
        ///</summary>
        [TestMethod]
        public void WriteToLog_Test()
        {
            bool allowToAll = true;
            bool allowToEventLog = false;
            bool allowToFile = false;
            string logPath = sBasePath + @"\SampleLog.log";

            if (logPath.ValidatePath(ePathValidation.File)) File.Delete(logPath);
            if (EventLog.Exists(sEventSource)) EventLog.Delete(sEventSource);

            MessageBox.Show("Select 'YES' in the next dialog boxes, if prompted..");
            Logger logger = new Logger(allowToAll, allowToEventLog, allowToFile, logPath);
            string logContents = "Test log-contents";
            DateTime? startTime = DateTime.Now;
            DateTime? completionTime = DateTime.Now;
            EventLogEntryType severity = EventLogEntryType.Information;

            Logger.WriteToLog(logger, logContents, startTime, completionTime, null, severity);

            System.Windows.Forms.MessageBox.Show("read_last_event_log_to_verify");
        }
    }
}
